package net.ming616.nlp.ontology.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import net.ming616.nlp.ontology.model.DataUnit;
import net.ming616.nlp.ontology.service.YagoManager;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.tdb.TDBFactory;

@Service("yagoManager")
public class YagoManagerImpl implements YagoManager {
	String baseURI = "http://www.mpii.de/yago/resource/";

	/**
	 * Logger for this class
	 */
	@SuppressWarnings("unused")
	private final Logger logger = Logger.getLogger(YagoManagerImpl.class);

	Model model = null;

	String prefix = " PREFIX resource: <" + baseURI + ">";

	public List<DataUnit> findByObject(String obj) {
		String sparqlQueryString = "";
		StringBuffer buffer = new StringBuffer();
		buffer.append(this.prefix);
		buffer.append(" SELECT ?subj ?relation ?obj");
		buffer.append(" WHERE {");
		buffer.append(" ?subj ?relation" + " \"" + obj + "\" . ");
		buffer.append(" }");
		sparqlQueryString = buffer.toString();
		List<DataUnit> result = this.query(sparqlQueryString);
		for (DataUnit du : result) {
			if (du.getObject() == null) {
				du.setObject(obj);
			}
		}
		return result;
	}

	public List<DataUnit> findBySubject(String subject) {
		String sparqlQueryString = "";
		StringBuffer buffer = new StringBuffer();
		buffer.append(this.prefix);
		buffer.append(" SELECT ?subj ?relation ?obj");
		buffer.append(" WHERE {");
		buffer.append("resource:" + subject + " ?relation ?obj . ");
		buffer.append(" }");
		sparqlQueryString = buffer.toString();
		List<DataUnit> result = this.query(sparqlQueryString);
		for (DataUnit du : result) {
			if (du.getSubject() == null) {
				du.setSubject(subject);
			}
		}
		return result;
	}

	@PostConstruct
	void generateModel() {
		// Create an empty Model
		String directory = "F:/yago2/converted";
		this.model = TDBFactory.createModel(directory);
	}

	public Resource generateResource(String resourceName) {
		Resource resource = this.model.createResource(this.baseURI
				+ resourceName);
		return resource;
	}

	private List<DataUnit> query(String sparqlQueryString) {
		List<DataUnit> result = new ArrayList<DataUnit>();
		Query query = QueryFactory.create(sparqlQueryString);
		QueryExecution qexec = QueryExecutionFactory.create(query, this.model);
		ResultSet queryResults = qexec.execSelect();

		while (queryResults.hasNext()) {
			DataUnit dataUnit = new DataUnit();
			QuerySolution soln = queryResults.next();
			String subj = null, relation = null, obj = null;
			if (soln.contains("?subj")) {
				subj = model.getResource(soln.get("subj").toString())
						.getLocalName();
			}
			if (soln.contains("?relation")) {
				relation = model.getResource(soln.get("relation").toString())
						.getLocalName();
			}
			if (soln.contains("?obj")) {
				RDFNode node = soln.get("obj");
				obj = node.toString();
			}
			dataUnit.setSubject(subj);
			dataUnit.setRelation(relation);
			dataUnit.setObject(obj);
			result.add(dataUnit);
		}
		qexec.close();
		return result;
	}

}
